﻿namespace eeenno.SpeeedReaderUI.NativeWebBrowser.Runtime.InteropServices
{
    using System;
    using System.Reflection;
    using System.Runtime.InteropServices;
    using System.Text;

    public sealed class MarshalEx
    {
        private const int GMEM_FIXED = 0;
        private static readonly int HIWORDMASK = -65536;
        private const int LMEM_MOVEABLE = 2;
        private const int LMEM_ZEROINIT = 0x40;
        private const int LPTR = 0x40;
        public static readonly int SystemDefaultCharSize = Marshal.SystemDefaultCharSize;

        private MarshalEx()
        {
        }

        public static IntPtr AllocHGlobal(int cb)
        {
            IntPtr ptr = LocalAlloc(0x40, (uint) cb);
            if (ptr == IntPtr.Zero)
            {
                throw new OutOfMemoryException();
            }
            return ptr;
        }

        public static IntPtr AllocHGlobal(IntPtr cb)
        {
            return AllocHGlobal((int) cb);
        }

        public static IntPtr AllocHLocal(int cb)
        {
            return LocalAlloc(0x40, (uint) cb);
        }

        [CLSCompliant(false)]
        public static IntPtr AllocHLocal(uint cb)
        {
            return LocalAlloc(0x40, cb);
        }

        public static void Copy(IntPtr source, byte[] destination, int startIndex, int length)
        {
            Marshal.Copy(source, destination, startIndex, length);
        }

        public static void Copy(IntPtr source, char[] destination, int startIndex, int length)
        {
            Marshal.Copy(source, destination, startIndex, length);
        }

        public static void Copy(IntPtr source, double[] destination, int startIndex, int length)
        {
            Marshal.Copy(source, destination, startIndex, length);
        }

        public static void Copy(IntPtr source, short[] destination, int startIndex, int length)
        {
            Marshal.Copy(source, destination, startIndex, length);
        }

        public static void Copy(IntPtr source, int[] destination, int startIndex, int length)
        {
            Marshal.Copy(source, destination, startIndex, length);
        }

        public static void Copy(IntPtr source, long[] destination, int startIndex, int length)
        {
            Marshal.Copy(source, destination, startIndex, length);
        }

        public static void Copy(IntPtr source, float[] destination, int startIndex, int length)
        {
            Marshal.Copy(source, destination, startIndex, length);
        }

        public static void Copy(byte[] source, int startIndex, IntPtr destination, int length)
        {
            Marshal.Copy(source, startIndex, destination, length);
        }

        public static void Copy(char[] source, int startIndex, IntPtr destination, int length)
        {
            Marshal.Copy(source, startIndex, destination, length);
        }

        public static void Copy(double[] source, int startIndex, IntPtr destination, int length)
        {
            Marshal.Copy(source, startIndex, destination, length);
        }

        public static void Copy(short[] source, int startIndex, IntPtr destination, int length)
        {
            Marshal.Copy(source, startIndex, destination, length);
        }

        public static void Copy(int[] source, int startIndex, IntPtr destination, int length)
        {
            Marshal.Copy(source, startIndex, destination, length);
        }

        public static void Copy(long[] source, int startIndex, IntPtr destination, int length)
        {
            Marshal.Copy(source, startIndex, destination, length);
        }

        public static void Copy(float[] source, int startIndex, IntPtr destination, int length)
        {
            Marshal.Copy(source, startIndex, destination, length);
        }

        public static void FreeHGlobal(IntPtr hGlobal)
        {
            if (!IsNotWin32Atom(hGlobal))
            {
                throw new ArgumentException("hGlobal is not an unmanaged atom.");
            }
            LocalFree(hGlobal);
        }

        public static void FreeHLocal(IntPtr hMem)
        {
            if (hMem != IntPtr.Zero)
            {
                LocalFree(hMem);
            }
        }

        public static IntPtr GetHINSTANCE(Module m)
        {
            IntPtr zero = IntPtr.Zero;
            if (m.Assembly == Assembly.GetCallingAssembly())
            {
                zero = GetModuleHandle(null);
            }
            else
            {
                zero = GetModuleHandle(m.Assembly.GetName().CodeBase);
            }
            if (zero == IntPtr.Zero)
            {
                return new IntPtr(-1);
            }
            return zero;
        }

        public static int GetLastWin32Error()
        {
            return Marshal.GetLastWin32Error();
        }

        [DllImport("coredll.dll", EntryPoint="GetModuleHandleW", SetLastError=true)]
        private static extern IntPtr GetModuleHandle(string lpszModule);
        public static bool IsComObject(object o)
        {
            return Marshal.IsComObject(o);
        }

        private static bool IsNotWin32Atom(IntPtr ptr)
        {
            long num = (long) ptr;
            return (0L != (num & HIWORDMASK));
        }

        [DllImport("coredll.dll", SetLastError=true)]
        private static extern IntPtr LocalAlloc(uint uFlags, uint Bytes);
        [DllImport("coredll.dll", SetLastError=true)]
        private static extern IntPtr LocalFree(IntPtr hMem);
        [DllImport("coredll.dll", EntryPoint="LocalReAlloc", SetLastError=true)]
        private static extern IntPtr LocalReAllocCE(IntPtr hMem, int uBytes, int fuFlags);
        private static int lstrlenW(IntPtr ptr)
        {
            return String_wcslen(ptr);
        }

        public static string PtrToStringAnsi(IntPtr ptr)
        {
            string str = "";
            byte num = 0;
            int ofs = 0;
            while (true)
            {
                num = Marshal.ReadByte(ptr, ofs);
                if (num == 0)
                {
                    return str;
                }
                str = str + ((char) num).ToString();
                ofs++;
            }
        }

        public static string PtrToStringAnsi(IntPtr ptr, int ofs, int len)
        {
            int length = len;
            byte[] destination = new byte[length];
            Marshal.Copy(new IntPtr(ptr.ToInt32() + ofs), destination, 0, length);
            string str = Encoding.ASCII.GetString(destination, 0, len);
            int index = str.IndexOf('\0');
            if (index > -1)
            {
                str = str.Substring(0, index);
            }
            return str;
        }

        public static string PtrToStringAuto(IntPtr ptr)
        {
            if (ptr == IntPtr.Zero)
            {
                return null;
            }
            string str = "";
            int num = Marshal.ReadByte(ptr, 0);
            int num2 = Marshal.ReadByte(ptr, 1);
            if (num == 0)
            {
                return str;
            }
            if (num2 != 0)
            {
                return PtrToStringAnsi(ptr);
            }
            if (Marshal.ReadByte(ptr, 2) == 0)
            {
                char ch = (char) num;
                return ch.ToString();
            }
            return Marshal.PtrToStringUni(ptr);
        }

        public static string PtrToStringUni(IntPtr ptr)
        {
            return Marshal.PtrToStringUni(ptr);
        }

        public static string PtrToStringUni(IntPtr ptr, int ofs, int len)
        {
            int length = len * Marshal.SystemDefaultCharSize;
            byte[] destination = new byte[length];
            Marshal.Copy(new IntPtr(ptr.ToInt32() + ofs), destination, 0, length);
            string str = Encoding.Unicode.GetString(destination, 0, len);
            int index = str.IndexOf('\0');
            if (index > -1)
            {
                str = str.Substring(0, index);
            }
            return str;
        }

        public static bool ReadBool(IntPtr ptr, int ofs)
        {
            byte[] destination = new byte[4];
            Marshal.Copy(new IntPtr(ptr.ToInt32() + ofs), destination, 0, 4);
            return Convert.ToBoolean(destination);
        }

        public static byte ReadByte(IntPtr ptr, int ofs)
        {
            return Marshal.ReadByte(ptr, ofs);
        }

        public static byte[] ReadByteArray(IntPtr ptr, int ofs, int len)
        {
            byte[] destination = new byte[len];
            Marshal.Copy(new IntPtr(ptr.ToInt32() + ofs), destination, 0, len);
            return destination;
        }

        public static char ReadChar(IntPtr ptr, int ofs)
        {
            byte[] destination = new byte[Marshal.SystemDefaultCharSize];
            Marshal.Copy(new IntPtr(ptr.ToInt32() + ofs), destination, 0, destination.Length);
            return BitConverter.ToChar(destination, 0);
        }

        public static short ReadInt16(IntPtr ptr, int ofs)
        {
            return Marshal.ReadInt16(ptr, ofs);
        }

        public static int ReadInt32(IntPtr ptr, int ofs)
        {
            return Marshal.ReadInt32(ptr, ofs);
        }

        public static long ReadInt64(IntPtr ptr, int ofs)
        {
            byte[] destination = new byte[8];
            Marshal.Copy(new IntPtr(ptr.ToInt32() + ofs), destination, 0, 8);
            return BitConverter.ToInt64(destination, 0);
        }

        public static IntPtr ReadIntPtr(IntPtr ptr, int ofs)
        {
            return new IntPtr(Marshal.ReadInt32(ptr, ofs));
        }

        [CLSCompliant(false)]
        public static ushort ReadUInt16(IntPtr ptr, int ofs)
        {
            byte[] destination = new byte[2];
            Marshal.Copy(new IntPtr(ptr.ToInt32() + ofs), destination, 0, 2);
            return BitConverter.ToUInt16(destination, 0);
        }

        [CLSCompliant(false)]
        public static uint ReadUInt32(IntPtr ptr, int ofs)
        {
            byte[] destination = new byte[4];
            Marshal.Copy(new IntPtr(ptr.ToInt32() + ofs), destination, 0, 4);
            return BitConverter.ToUInt32(destination, 0);
        }

        [CLSCompliant(false)]
        public static ulong ReadUInt64(IntPtr ptr, int ofs)
        {
            byte[] destination = new byte[8];
            Marshal.Copy(new IntPtr(ptr.ToInt32() + ofs), destination, 0, 8);
            return BitConverter.ToUInt64(destination, 0);
        }

        public static IntPtr ReAllocHGlobal(IntPtr pv, IntPtr cb)
        {
            IntPtr ptr = LocalReAllocCE(pv, (int) cb, 0x40);
            if (ptr == IntPtr.Zero)
            {
                throw new OutOfMemoryException();
            }
            return ptr;
        }

        public static int SizeOf(object structure)
        {
            return Marshal.SizeOf(structure);
        }

        public static int SizeOf(Type t)
        {
            return Marshal.SizeOf(t);
        }

        [DllImport("mscoree.dll", EntryPoint="#1", SetLastError=true)]
        private static extern int String_wcslen(IntPtr pws);
        public static IntPtr StringToHGlobalAnsi(string s)
        {
            if (s == null)
            {
                return IntPtr.Zero;
            }
            int num = s.Length + 1;
            IntPtr destination = LocalAlloc(0x40, (uint) num);
            byte[] bytes = Encoding.ASCII.GetBytes(s);
            Marshal.Copy(bytes, 0, destination, bytes.Length);
            return destination;
        }

        public static IntPtr StringToHGlobalUni(string s)
        {
            if (s == null)
            {
                return IntPtr.Zero;
            }
            int num = (s.Length + 1) * 2;
            IntPtr destination = LocalAlloc(0x40, (uint) num);
            byte[] bytes = Encoding.Unicode.GetBytes(s);
            Marshal.Copy(bytes, 0, destination, bytes.Length);
            return destination;
        }

        public static void StructureToPtr(object structure, IntPtr ptr, bool fDeleteOld)
        {
            Marshal.StructureToPtr(structure, ptr, fDeleteOld);
        }

        [CLSCompliant(false)]
        public static DateTime Time_tToDateTime(uint time_t)
        {
            long fileTime = (0x989680L * time_t) + 0x19db1ded53e8000L;
            return DateTime.FromFileTimeUtc(fileTime);
        }

        public static void WriteBool(IntPtr ptr, int ofs, bool val)
        {
            byte[] bytes = BitConverter.GetBytes(val);
            Marshal.Copy(bytes, 0, new IntPtr(ptr.ToInt32() + ofs), bytes.Length);
        }

        public static void WriteByte(IntPtr ptr, int ofs, byte val)
        {
            Marshal.WriteByte(ptr, ofs, val);
        }

        public static void WriteByteArray(IntPtr ptr, int ofs, byte[] val)
        {
            Marshal.Copy(val, 0, new IntPtr(ptr.ToInt32() + ofs), val.Length);
        }

        public static void WriteChar(IntPtr ptr, int ofs, char val)
        {
            byte[] bytes = BitConverter.GetBytes(val);
            Marshal.Copy(bytes, 0, new IntPtr(ptr.ToInt32() + ofs), bytes.Length);
        }

        public static void WriteInt16(IntPtr ptr, int ofs, short val)
        {
            Marshal.WriteInt16(ptr, ofs, val);
        }

        public static void WriteInt32(IntPtr ptr, int ofs, int val)
        {
            Marshal.WriteInt32(ptr, ofs, val);
        }

        public static void WriteInt64(IntPtr ptr, int ofs, long val)
        {
            byte[] bytes = BitConverter.GetBytes(val);
            Marshal.Copy(bytes, 0, new IntPtr(ptr.ToInt32() + ofs), bytes.Length);
        }

        public static void WriteIntPtr(IntPtr ptr, int ofs, IntPtr val)
        {
            WriteInt32(ptr, ofs, val.ToInt32());
        }

        [CLSCompliant(false)]
        public static void WriteUInt16(IntPtr ptr, int ofs, ushort val)
        {
            byte[] bytes = BitConverter.GetBytes(val);
            Marshal.Copy(bytes, 0, new IntPtr(ptr.ToInt32() + ofs), bytes.Length);
        }

        [CLSCompliant(false)]
        public static void WriteUInt32(IntPtr ptr, int ofs, uint val)
        {
            byte[] bytes = BitConverter.GetBytes(val);
            Marshal.Copy(bytes, 0, new IntPtr(ptr.ToInt32() + ofs), bytes.Length);
        }

        [CLSCompliant(false)]
        public static void WriteUInt64(IntPtr ptr, int ofs, ulong val)
        {
            byte[] bytes = BitConverter.GetBytes(val);
            Marshal.Copy(bytes, 0, new IntPtr(ptr.ToInt32() + ofs), bytes.Length);
        }
    }
}

